﻿using Codeplex.STSDTS.MSBuildTasks.TestServices;
using Microsoft.Build.Framework;
using System.Net;
using Codeplex.STSDTS.Entities;
using System;

namespace Codeplex.STSDTS.MSBuildTasks
{

    /// <summary>
    /// Class representing a build task for use with Team Foundation Build.
    /// This task invokes the STSDTS deployment web service and downloads the solutions as described in the farm XML file.
    /// </summary>
    public class TestFarm : BaseTask
    {

        #region Properties

        /// <summary>
        /// Url of the deployment web service
        /// </summary>
        [Required]
        public string TestServiceUrl
        {
            get;
            set;
        }

        /// <summary>
        /// Location of the farm XML file
        /// </summary>
        [Required]
        public string FarmFile
        {
            get;
            set;
        }

        /// <summary>
        /// Username for calling the deployment web service
        /// </summary>
        [Required]
        public string UserName
        {
            get;
            set;
        }

        /// <summary>
        /// Password for calling the deployment web service
        /// </summary>
        [Required]
        public string Password
        {
            get;
            set;
        }

        /// <summary>
        /// Domain for calling the deployment web service
        /// </summary>
        public string Domain
        {
            get;
            set;
        }


        private TestService _testService;

        #endregion Properties

        override public bool Execute()
        {

            //Load farm file
            var farm = Farm.Deserialize(FarmFile);

            //Setup test service with given credentials
            _testService = new TestService
                                        {
                                            Credentials =
                                                new NetworkCredential
                                                {
                                                    UserName = UserName,
                                                    Password = Password
                                                },
                                            Url = TestServiceUrl
                                        };
            //Also set domain if it is not null or empty
            if (!string.IsNullOrEmpty(Domain))
                ((NetworkCredential)_testService.Credentials).Domain = Domain;

            return TestSolutionDeployed(farm);
        }

        private bool TestSolutionDeployed(Farm farm)
        {
            var result = true;
            foreach (var solution in farm.Solutions)
            {
                var taskId = CreateBuildStep("Verify: Installed {0}", solution.FileName);
                var tempResult = _testService.SolutionExists(solution.Id);
                EndBuildStep(taskId, tempResult);
                if (!tempResult)
                    result = false;

                taskId = CreateBuildStep("Verify: Deployed {0}", solution.FileName);
                if (solution.WebApplications.Count == 0)
                {
                    tempResult = _testService.SolutionDeployedOnWebApplication(solution.Id, null);
                    EndBuildStep(taskId, tempResult);
                    if (!tempResult)
                    result = false;
                }
                else
                {
                    var totalResult = true;
                    foreach (var webApplication in solution.WebApplications)
                    {
                        var taskId2 = CreateBuildStep("Verify: Deployed {0} on {1}", solution.FileName, webApplication.Url);
                        var check = _testService.SolutionDeployedOnWebApplication(solution.Id, webApplication.Url);
                        EndBuildStep(taskId2, check);
                        if (!check)
                            totalResult = false;
                    }
                    EndBuildStep(taskId, totalResult);
                    if (!totalResult)
                        result = false;
                }
                //Invoke testing feature activation
                var featureTestResult = TestFeaturesActivated(solution);
                if (!featureTestResult)
                    result = false;
            }
            return result;
        }

        private bool TestFeaturesActivated(Solution solution)
        {
            var testResult = true;
            foreach (var feature in solution.Features)
            {
                Guid taskId;
                bool check;
                foreach (var webApplication in feature.WebApplications)
                {
                    taskId = CreateBuildStep("Verify: Feature {0} activated on {1}", feature.Id, webApplication.Url);
                    check = _testService.FeatureActivatedOnWebApplication(feature.Id, webApplication.Url);
                    EndBuildStep(taskId, check);
                    testResult = check ? testResult : false;
                }
                foreach (var siteCollection in feature.SiteCollections)
                {
                    taskId = CreateBuildStep("Verify: Feature {0} activated on {1}", feature.Id, siteCollection.Url);
                    check = _testService.FeatureActivatedOnSiteCollection(feature.Id, siteCollection.Url);
                    EndBuildStep(taskId, check);
                    testResult = check ? testResult : false;
                }
                foreach (var site in feature.Sites)
                {
                    taskId = CreateBuildStep("Verify: Feature {0} activated on {1}", feature.Id, site.Url);
                    check = _testService.FeatureActivatedOnSite(feature.Id, site.Url);
                    EndBuildStep(taskId, check);
                    testResult = check ? testResult : false;
                }
            }
            return testResult;
        }

    }
}
